/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.wikimark;

import java.util.HashSet;
import java.util.Set;

class Bredogen {
    private final String[] ids;
    private final char minChar = 'a';
    private final char maxChar = 'z';
    private final int maxWord = 10;
    private final int maxPhrase = 100;
    private final int maxParagraph = 500;
    private final int maxHeading = 25;
    private final int maxBullets = 10;
    
    private final float refDencity = 0.05F;
    private final PageFormatter pageFormatter;
    
    Bredogen(PageFormatter pageFormatter, int idCount) {        
        this.pageFormatter = pageFormatter;
        Set<String> idSet = new HashSet<String>(idCount);
        while (idSet.size() < idCount) {
            idSet.add(createWord(true, pageFormatter.requiresCamelCase()));
        }
        ids = idSet.toArray(new String[idSet.size()]);
    }
        
    String[] getIds() {
        return ids;
    }

    private String createWord(boolean id, boolean capitalLetter) {
        int length = random(id && pageFormatter.requiresCamelCase() ? 4 : 1, maxWord);
        StringBuilder res = new StringBuilder(length);
        char first = createChar(id);
        res.append(capitalLetter ? Character.toUpperCase(first) : first);
        for (int i = 1; i < length; i++) {
            res.append(createChar(id));
        }
        if (id && pageFormatter.requiresCamelCase()) {
            int secondCapital = random(2, res.length() - 2);
            res.setCharAt(secondCapital, Character.toUpperCase(res.charAt(secondCapital)));
        }
        return res.toString();
    }
    
    private String createRef(String word) {
    	return pageFormatter.createRef(ids[random(0, ids.length - 1)], word);
    }
    
    private String createPhrase(int chars, boolean refs) {
        StringBuilder res = new StringBuilder(chars + maxWord);
        res.append(createWord(false, true));
        while (res.length() < chars) {
            res.append(' ');
            String word = createWord(false, false);
            String part = !refs || Math.random() > refDencity ? word
                    : createRef(word);            
            res.append(part);
        }
        return res.toString();
    }
    
    private String createParagraph(int chars) {
        StringBuilder res = new StringBuilder(chars + maxWord);
        while (res.length() < chars) {
            int phraseLength = Math.min(random(1, maxPhrase), chars
                    - res.length());
            res.append(createPhrase(phraseLength, true)).append(".\r\n");
        }
        res.append("\r\n");
        return res.toString();
    }
    
    String createText(int chars) {
        return createTree(chars, 0);
    }
    
    private String createTree(int chars, int level) {
        StringBuilder res = new StringBuilder(chars + maxPhrase);
        String title = createPhrase(maxHeading, false);
        res.append(createHeading(title, level));
        res.append(createParagraph(maxParagraph));
        if (chars - res.length() > 0) {
            for (int bullets = random(1, maxBullets); bullets > 0
                    && res.length() < chars; bullets--) {
                res.append(createTree((chars - res.length())/bullets, level + 1));
            }
        }
        return res.toString();
    }
    
    private char createChar(boolean id) {
        int min = id ? 'a' : minChar;
        int max = id ? 'z' : maxChar;
        return (char)random(min, max);
    }
    
    private String createHeading(String phrase, int level) {
        return pageFormatter.createHeader(phrase, level);
    }
    
    private static int random(int min, int max) {
        return (int)(min + (max - min + 1) * Math.random());
    }
}
